import { useEffect, useRef } from "react";
import repleceColor, { getNewCanvas, REPLACECOLOR } from "@/util/repleceColor";
import { Button, FormProps, Form, Upload, UploadProps, Select } from "antd";
import { DownloadOutlined, InboxOutlined } from "@ant-design/icons";
import { throttle } from "lodash";
import EraseImg, { SetErase } from "./handelOptions/EraseImg";
import ReplaceColorOption from "./handelOptions/ReplaceColorOption";
import "./index.less";
const { Dragger } = Upload;
export type FieldType = {
  handleType: number;
  targetColor?: string;
  precision?: number;
  eraseShape?: number;
  erasSeize?: number;
  myPicture: any;
  format: string;
};
export enum ERASETYPE {
  circle = 1, //圆
  square = 2, //方形
  triangle = 3, //三角
}
export type IMGPosition = {
  imgX: number;
  imgY: number;
  imgWidth: number;
  imgHeight: number;
};
enum HANDLETYPE {
  replece_color = 1, //换色
  clip = 2, //裁剪
  matting = 3, //抠图
  erase = 4, //橡皮擦
}
const defaultOptionValue = {
  targetColor: "#1677ff",
  precision: 10,
  format: "png",
  handleType: HANDLETYPE.replece_color,
  eraseShape: ERASETYPE.circle,
  erasSeize: 20,
};

const HandelImage = () => {
  const myImage = useRef<HTMLCanvasElement>(null);
  const imgSrc = useRef("");
  const eraseIsMousemoveing = useRef<boolean>(false);
  const imgPosition = useRef<IMGPosition>();
  const [form] = Form.useForm();
  const handleType = Form.useWatch("handleType", form);
  const eraseShape = Form.useWatch("eraseShape", form);
  const erasSeize = Form.useWatch("erasSeize", form);

  //初始化canvas图片
  const initPic = (ctx: CanvasRenderingContext2D, url: string) => {
    const canvas = myImage.current as HTMLCanvasElement;
    console.log({ canvas: myImage.current, url });
    // 创建一个图片的实例
    const img = new Image();
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    img.onload = () => {
      // 设置画布的宽高与图片的保持一致
      let canvasWidth = canvas.width;
      let canvasHeight = canvas.height;

      let imgWidth = img.width;
      let imgHeight = img.height;

      let scaleWidth = canvasWidth / imgWidth;
      let scaleHeight = canvasHeight / imgHeight;

      // 选择缩放比例小的那个，以保持图片的宽高比
      let scale = Math.min(scaleWidth, scaleHeight);

      // 计算缩放后的图片尺寸
      let width = imgWidth * scale;
      let height = imgHeight * scale;

      // 计算图片在canvas中的位置（居中）
      let x = (canvasWidth - width) / 2;
      let y = (canvasHeight - height) / 2;
      // 绘制图片
      ctx.drawImage(img, x, y, width, height);
      imgPosition.current = {
        imgX: x,
        imgY: y,
        imgWidth: width,
        imgHeight: height,
      };
    };
    // 引入图片的地址
    img.src = url;
  };

  const getCtx = (): CanvasRenderingContext2D =>
    myImage.current?.getContext("2d") as CanvasRenderingContext2D;

  //上传图片回调
  const fileChage = (file: File) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      const url = event.target?.result as string;
      imgSrc.current = url;
      initPic(getCtx(), url);
    };
    reader.readAsDataURL(file);
  };

  // 获取点击canvas的x坐标
  const getOffset = (e: any): { offsetX: number; offsetY: number } => {
    let X: number = e.clientX;
    let Y: number = e.clientY;
    let thisDiv = e.currentTarget; //获取实例
    let thisDivObj = thisDiv.getBoundingClientRect(); //object、有相对与容器的坐标
    X = X - Math.round(thisDivObj.left); //相对父级的x
    Y = Y - Math.round(thisDivObj.top); //相对父级的y
    return {
      offsetX: Number(X.toFixed(2)),
      offsetY: Number(Y.toFixed(2)),
    };
  };
  // 下载图片
  const downLoadPicture: FormProps<FieldType>["onFinish"] = (values) => {
    const name: string = values.myPicture[0].name;
    const format: string = form.getFieldValue("format");
    const preFormat = name.split(".").pop() as string;

    if (!!imgSrc.current) {
      // 创建一个临时的a标签
      var a = document.createElement("a");
      // 将base64设置为href属性，并确保URL编码（如果需要的话）
      a.href = imgSrc.current;
      // 设置下载的文件名
      a.download = name.replace(preFormat, format);
      // 模拟点击
      document.body.appendChild(a);
      a.click();
      // 清理
      document.body.removeChild(a);
    }
  };
  //失败回调
  const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (
    errorInfo
  ) => {
    console.log("失败:", errorInfo);
  };

  const resizeInit = throttle(initPic, 500);

  useEffect(() => {
    form.setFieldsValue(defaultOptionValue);
    const ctx = getCtx();
    const event = (_e: any) => {
      //改色后会收到新的base64，因此这个base64是整个canvas的大小改色后重新放置区域会有bug
      resizeInit(ctx, imgSrc.current);
    };

    window.addEventListener("resize", event);
    return () => {
      window.removeEventListener("resize", event);
    };
  }, []);

  const uploadProps: UploadProps = {
    name: "file",
    accept: ".png,.jpg,.webp,.jpeg",
    multiple: false,
    maxCount: 1,
    beforeUpload: (file: File) => {
      console.log("beforeUpload", file);
      fileChage(file);
      return false;
    },
    onRemove(_file: any) {
      imgSrc.current = "";
      const canvas = myImage.current as HTMLCanvasElement;
      getCtx().clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
    },
  };
  //图片换色
  const hanldeRepleceColor = (e: any) => {
    const { offsetX, offsetY } = getOffset(e);
    const { targetColor, precision, format } = form.getFieldsValue([
      "targetColor",
      "precision",
      "format",
    ]);

    const params: REPLACECOLOR = {
      x: offsetX,
      y: offsetY,
      canvas: myImage.current as HTMLCanvasElement,
      targetColor: targetColor.toHex ? `#${targetColor.toHex()}` : targetColor, // 目标色值
      precision,
      format,
      imgPosition: imgPosition.current,
    };

    repleceColor(params).then((base64) => {
      console.log({ base64 });
      imgSrc.current = base64;
    });
  };

  //橡皮擦
  const handleEraseImg = (e: any) => {
    const { offsetX, offsetY } = getOffset(e);
    const format: string = form.getFieldValue("format");
    switch (eraseShape) {
      case ERASETYPE.square:
        const x = offsetX - erasSeize / 2;
        const y = offsetY - erasSeize / 2;
        getCtx().clearRect(x, y, erasSeize, erasSeize);
        break;
      case ERASETYPE.circle:
        break;
      case ERASETYPE.triangle:
        break;
    }
    if (eraseIsMousemoveing.current) return;
    const newCanvas = getNewCanvas(
      getCtx(),
      imgPosition.current as IMGPosition
    );
    const base64 = newCanvas.toDataURL(`image/${format}`);
    imgSrc.current = base64;
  };

  // 操作区域的操作dom
  const getHandleImgOption = (handleType: number) => {
    const optionConf: Record<number, any> = {
      [HANDLETYPE.replece_color]: <ReplaceColorOption />,
      [HANDLETYPE.erase]: <EraseImg form={form} eraseShape={eraseShape} />,
    };
    return optionConf[handleType];
  };

  const canvasClick = (e: any) => {
    if (!imgSrc.current) return;
    const handleType = form.getFieldValue("handleType");
    const methods: Record<number, Function> = {
      [HANDLETYPE.replece_color]: hanldeRepleceColor,
      [HANDLETYPE.clip]: () => {},
      [HANDLETYPE.matting]: () => {},
      [HANDLETYPE.erase]: handleEraseImg,
    };
    methods[handleType](e);
  };

  const onMouseDown = (_e: any) => {
    eraseIsMousemoveing.current = true;
    if (handleType !== HANDLETYPE.erase) return;
    myImage.current?.addEventListener("mousemove", handleEraseImg);
  };
  const onMouseUp = (e: any) => {
    eraseIsMousemoveing.current = false;
    canvasClick(e);
    if (handleType !== HANDLETYPE.erase) return;
    myImage.current?.removeEventListener("mousemove", handleEraseImg);
  };
  return (
    <div className="P-account  over-hidden flex flexJc-space-between wp-100 hp-100">
      <div className="handle-area">
        <Form
          form={form}
          labelCol={{ span: 10 }}
          wrapperCol={{ span: 15 }}
          style={{ width: 330 }}
          initialValues={{ remember: true }}
          onFinish={downLoadPicture}
          onFinishFailed={onFinishFailed}
          autoComplete="off"
        >
          <Form.Item<FieldType>
            label="处理类型"
            name="handleType"
            rules={[{ required: true, message: "请选择处理类型" }]}
          >
            <Select
              options={[
                { value: HANDLETYPE.replece_color, label: "换色" },
                { value: HANDLETYPE.clip, label: "裁剪", disabled: true },
                { value: HANDLETYPE.matting, label: "抠图", disabled: true },
                { value: HANDLETYPE.erase, label: "橡皮擦", disabled: false },
              ]}
            />
          </Form.Item>
          {getHandleImgOption(handleType)}
          <Form.Item<FieldType>
            label="图片格式"
            tooltip="下载时的图片格式，在为改色前只是改了后缀名"
            name="format"
            rules={[{ required: true, message: "请选择导出格式" }]}
          >
            <Select
              options={[
                { value: "png", label: "png" },
                { value: "jpg", label: "jpg" },
                { value: "jpeg", label: "jpeg" },
                { value: "webp", label: "webp" },
              ]}
            />
          </Form.Item>
          <Form.Item<FieldType>
            label="目标图片"
            name="myPicture"
            valuePropName="fileList"
            rules={[{ required: true, message: "请上传图片" }]}
            getValueFromEvent={(e: any) => (Array.isArray(e) ? e : e?.fileList)}
          >
            <Dragger {...uploadProps}>
              <p className="ant-upload-drag-icon">
                <InboxOutlined />
              </p>
            </Dragger>
          </Form.Item>
          <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
            <Button htmlType="submit" icon={<DownloadOutlined />}>
              下载
            </Button>
          </Form.Item>
        </Form>
      </div>
      <div id="drow-area" className="drow-area hp-100 relative">
        {handleType === HANDLETYPE.erase && (
          <SetErase className="set-erase" size={erasSeize} type={eraseShape} />
        )}
        <canvas
          className="canvas  wp-100 hp-100"
          onMouseUp={onMouseUp}
          onMouseDown={onMouseDown}
          ref={myImage}
        />
      </div>
    </div>
  );
};

export default HandelImage;
